//实现一个事件监听器，支持链式调用
//on接收事件名与监听器
//once与on类似，但只会触发一次
//emit派发事件，第一个参数为事件名，其他参数为传递参数
//off第二个参数为取消该事件的监听器，可选，不填则为取消该事件名所有的监听
//allOf取消当前事件所有的监听，不传参数为取消所有事件监听。

export default class EventEmitter {
    constructor() {
        this.events = {}
        this.currentOnce = false
    }
    on(eventName, listener) {
        if (!eventName && typeof eventName !== 'string') {
            throw('eventName must be a string')
        }
        if (!listener && typeof listener !== 'function') {
            throw('listener must be a function')
        }
        let listeners = this.events[eventName] || []
        listeners.push({
            listener: listener,
            once: this.currentOnce,
        })
        this.events[eventName] = listeners
        this.currentOnce = false
        return this
    }
    once(eventName, listener) {
        this.currentOnce = true
        this.on(eventName, listener)
        return this
    }
    emit(eventName, arg) {
        let listeners = this.events[eventName]
        if (!listeners) return this
        listeners.forEach(listener => {
            listener.listener(arg)
            if (listener.once) {
                this.off(eventName, listener.listener)
            }
        })
        return this
    }
    off(eventName, listener) {
        if (!eventName && typeof eventName !== 'string') {
            throw('eventName must be a string')
        }
        if (!listener && listener === undefined) {
            this.events[eventName] = []
            return this
        }
        let listeners = this.events[eventName]
        if (!listeners) return this
        let index = listeners.findIndex(v => v.listener === listener)
        if (index > -1) {
            listeners.splice(index, 1)
        }
        return this
    }
    allOff(eventName) {
        if (eventName === undefined) {
            this.events = {}
        } else {
            this.events[eventName] = []
        }
        return this
    }
}